package com.tuo51.wx.mp.controller;

import com.alibaba.fastjson.JSON;
import com.tuo51.evaluate.domain.childrens.Children;
import com.tuo51.core.domain.staffs.Staff;
import com.tuo51.evaluate.service.ChildrenService;
import com.tuo51.core.service.StaffService;
import com.tuo51.foudation.constant.CommonConstant;
import com.tuo51.foudation.model.ErrorCode;
import com.tuo51.foudation.model.MemVerificationCache;
import com.tuo51.foudation.model.StatusResponse;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import static com.tuo51.foudation.constant.RequestConstant.TICKET;

/**
 * 微信小程序用户接口
 *
 */
@RestController
@RequestMapping("/mp/api/{appId}/auth")
@ApiOperation("微信服务号前端鉴权")
@Slf4j
public class WxMpAuthController {

    @Autowired
    private ChildrenService childrenService;

    @Autowired
    StaffService staffService;

    @Autowired
    MemVerificationCache cache;

    @Autowired
    private WxMpService wxService;

//    @Value("${wx.mp.defaultRedirect}")
//    private String defaultRedirect;

    //for special config， official and knsh
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    @ApiOperation(value = "微信登录接口", notes = "如果前端已经存储有ticket，请直接使用，否则返回 2000002 时需跳转，客户端应直接跳转 data 内指定地址")
    public StatusResponse login(HttpServletRequest req,
                                HttpServletResponse resp,
                                @PathVariable String appId,
                                @RequestHeader(value = TICKET, required = false) String ticket,
                                @RequestParam(required = false) String redirect,
                                @RequestParam(required = false) String ref,
                                @RequestParam(required = false) String refType){

        //直接返回用户
        String sessionTicket = (String) req.getSession().getAttribute("ticket");
        if (StringUtils.isEmpty(ticket) && StringUtils.isNotEmpty(sessionTicket)){
            ticket = sessionTicket;
        }
        if (StringUtils.isNotEmpty(ticket)) {
            String staffId = cache.getStaffIdWithNoException(ticket);
            if (StringUtils.isNotEmpty(staffId)) {
                Staff staff = staffService.getById(staffId);
                Map result = new HashMap();
                result.put("user", staff);
                result.put("ticket", ticket);

                Children children = childrenService.defaultChildrenForParent(staff, false);
                if (children != null){
                    result.put("default", children);
                }

                return StatusResponse.success(result);
            } else {
                req.getSession().removeAttribute("ticket");
            }
        }

        //
        String host = req.getServerName();
        String backUrl = req.getScheme() + "://" + host + "/mp/api/" + appId + "/auth/loginConfirm";
        if(!StringUtils.isEmpty(redirect)){
            backUrl = backUrl + "?redirect="+redirect;
        }
        if (!StringUtils.isAnyEmpty(ref, refType)){
            if (backUrl.contains("?")){
                backUrl = backUrl + "&ref=" + ref + "&refType=" + refType;
            }else{
                backUrl = backUrl + "?ref=" + ref + "&refType=" + refType;
            }
        }

        log.info("LOGIN   host ::: " + host);
        log.info("LOGIN   backUrl ::: " + backUrl);

        // 前端强制跳转URL
        // 获取授权链接
        String url = wxService.switchoverTo(appId).oauth2buildAuthorizationUrl(backUrl, WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);

        log.info("LOGIN auth url ::: " + url);

        return StatusResponse.of(ErrorCode.WX_HAVE_TO_REDIRECT, "have to redirect", url);
    }

    @RequestMapping(value = "/loginConfirm", method = RequestMethod.GET)
    @ApiOperation(value = "微信服务器鉴权回调", notes = "客户端不应该关心这个接口")
    public StatusResponse loginConfirm(HttpServletRequest req,
                                       HttpServletResponse resp,
                                       @PathVariable String appId,
                                       String code, @RequestParam(required = false ) String redirect) throws IOException {
        log.info("loginConfirm :::" + req.getRequestURI());

        int platform = CommonConstant.Platform.WXMP.codeOf();

        try {
            WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxService.switchoverTo(appId).oauth2getAccessToken(code);

            WxMpUser wxMpUser = wxService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);

            log.info("WxUser:{}",wxMpUser.toString());

            Staff wxUser = null;
            if( StringUtils.isNotEmpty(wxMpUser.getUnionId())){
                wxUser = staffService.getUnionID(wxMpUser.getUnionId(), appId);
            }
            if(wxUser == null){
                wxUser = staffService.getOpenIDMP(wxMpUser.getOpenId(), appId);
            }

            if(wxUser == null){
                wxUser = staffService.add(null, wxMpUser.getOpenId(), wxMpUser.getUnionId(), null, appId, CommonConstant.Platform.WXMP);
                log.info("create new wxuser:{}", wxUser);
            }

            //登陆成功后总是更新用户
            wxUser.setTemporally(false); //处理临时账户
            staffService.updateMpUserInfo(wxUser, wxMpUser);

            //return ticket
            String ticket = cache.produceTicket(wxUser.getId(), platform);

            //保存session
            req.getSession().setAttribute("ticket", ticket);

            //保存cookies
            Cookie c1 = new Cookie("ticket", ticket);
            Cookie c2 = new Cookie("user", URLEncoder.encode(JSON.toJSONString(wxUser), "UTF-8"));

            c1.setDomain(req.getServerName());
            c2.setDomain(req.getServerName());

            resp.addCookie(c1);
            resp.addCookie(c2);

//            if (StringUtils.isEmpty(redirect)){
//                redirect = defaultRedirect;
//            }
//            if (redirect.contains("?")){
//                redirect += "&";
//            }else{
//                redirect += "?";
//            }
//            redirect += "ticket=" + ticket;

            //跳转
            if (StringUtils.isNotEmpty(redirect)){
                //追加redirect
                if (redirect.contains("?")){
                    redirect = redirect + "&" + "ticket=" + ticket;
                }else{
                    redirect = redirect + "?" + "ticket=" + ticket;
                }

                resp.sendRedirect(redirect);

                return null;
            }else{
                return StatusResponse.success();
            }
        } catch (WxErrorException e) {
            e.printStackTrace();
            return StatusResponse.error(ErrorCode.WX_GET_USERINFO_FAILED, "获取微信用户数据时失败");
        }
    }
}
